tdf#118308: Incorrect Paste Special dialog when ...

pasting content from another cell

In tiled rendering case (headless) each window has its own clipboard,
otherwise exists a unique clipboard (UNO service).

Change-Id: I7d5d0b085faeaffa3fc0a80914fbe9349f4aa402
Reviewed-on: https://gerrit.libreoffice.org/56508
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack@redhat.com>
diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx
index 5313f87..01ac014 100644
--- a/sc/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx
@@ -15,6 +15,7 @@
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <com/sun/star/frame/Desktop.hpp>
#include <com/sun/star/frame/DispatchHelper.hpp>
#include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
#include <comphelper/dispatchcommand.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertysequence.hxx>
@@ -1551,12 +1552,17 @@
    // view #1
    ScTabViewShell* pView1 = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
    CPPUNIT_ASSERT(pView1);
    // emulate clipboard
    pView1->GetViewData().GetActiveWin()->SetClipboard(css::datatransfer::clipboard::SystemClipboard::create(comphelper::getProcessComponentContext()));

    // view #2
    SfxLokHelper::createView();
    ScTabViewShell* pView2 = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
    // emulate clipboard
    pView2->GetViewData().GetActiveWin()->SetClipboard(css::datatransfer::clipboard::SystemClipboard::create(comphelper::getProcessComponentContext()));
    CPPUNIT_ASSERT(pView2);
    CPPUNIT_ASSERT(pView1 != pView2);
    CPPUNIT_ASSERT(pView1->GetViewData().GetActiveWin()->GetClipboard() != pView2->GetViewData().GetActiveWin()->GetClipboard());

    // copy text view 1
    pView1->SetCursor(0, 0);
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 40d6107..474bf7e 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -2786,24 +2786,11 @@

ScDocument* ScDocShell::GetClipDoc()
{
    css::uno::Reference<css::datatransfer::XTransferable2> xTransferable;

    vcl::Window* pWin = nullptr;
    if (ScTabViewShell* pViewShell = GetBestViewShell())
        xTransferable.set(pViewShell->GetClipData());
    else
    {
        SfxViewFrame* pViewFrame = nullptr;
        css::uno::Reference<css::datatransfer::clipboard::XClipboard> xClipboard;
        pWin = pViewShell->GetViewData().GetActiveWin();

        if ((pViewFrame = SfxViewFrame::GetFirst(this, false)))
            xClipboard = pViewFrame->GetWindow().GetClipboard();
        else if ((pViewFrame = SfxViewFrame::GetFirst()))
             xClipboard = pViewFrame->GetWindow().GetClipboard();

        xTransferable.set(xClipboard.is() ? xClipboard->getContents() : nullptr, css::uno::UNO_QUERY);
    }

    const ScTransferObj* pObj = ScTransferObj::GetOwnClipboard(xTransferable);
    const ScTransferObj* pObj = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin));
    if (pObj)
    {
        ScDocument* pDoc = pObj->GetDocument();
diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx
index 2181e61..8b4753e 100644
--- a/sc/source/ui/inc/tabvwsh.hxx
+++ b/sc/source/ui/inc/tabvwsh.hxx
@@ -167,9 +167,6 @@
    OUString   maName;
    OUString   maScope;

    // ClipData
    css::uno::Reference<css::datatransfer::XTransferable2>   m_xClipData;

private:
    void    Construct( TriState nForceDesignMode );

@@ -394,9 +391,7 @@
    static void notifyAllViewsHeaderInvalidation(bool Columns, SCTAB nCurrentTabIndex);
    static bool isAnyEditViewInRange(bool bColumns, SCCOLROW nStart, SCCOLROW nEnd);
    css::uno::Reference<css::drawing::XShapes> getSelectedXShapes();

    const css::uno::Reference<css::datatransfer::XTransferable2> & GetClipData() { return m_xClipData; };
    void SetClipData(const css::uno::Reference<css::datatransfer::XTransferable2>& xTransferable) { m_xClipData = xTransferable; }
    static  css::uno::Reference<css::datatransfer::XTransferable2> GetClipData(vcl::Window* pWin);
};

#endif
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index 107fe23..0de0757 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -1132,7 +1132,7 @@
    {
        ScTabViewShell* pViewSh = static_cast<ScTabViewTarget&>(rTarget).GetViewShell();
        // keep a reference in case the clipboard is changed during PasteFromClip
        const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(pViewSh->GetClipData());
        const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pViewSh->GetViewData().GetActiveWin()));
        if (pOwnClip)
        {
            pViewSh->PasteFromClip( nFlags, pOwnClip->GetDocument(),
diff --git a/sc/source/ui/vba/excelvbahelper.cxx b/sc/source/ui/vba/excelvbahelper.cxx
index 0bcd3fb..b96821b 100644
--- a/sc/source/ui/vba/excelvbahelper.cxx
+++ b/sc/source/ui/vba/excelvbahelper.cxx
@@ -171,7 +171,7 @@
        pViewShell->CopyToClip(nullptr,false,false,true);

        // mark the copied transfer object so it is used in ScVbaRange::Insert
        uno::Reference<datatransfer::XTransferable2> xTransferable(pViewShell->GetClipData());
        uno::Reference<datatransfer::XTransferable2> xTransferable(ScTabViewShell::GetClipData(pViewShell->GetViewData().GetActiveWin()));
        ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard(xTransferable);
        if (pClipObj)
        {
@@ -191,7 +191,7 @@
        pViewShell->CutToClip();

        // mark the copied transfer object so it is used in ScVbaRange::Insert
        uno::Reference<datatransfer::XTransferable2> xTransferable(pViewShell->GetClipData());
        uno::Reference<datatransfer::XTransferable2> xTransferable(ScTabViewShell::GetClipData(pViewShell->GetViewData().GetActiveWin()));
        ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard(xTransferable);
        if (pClipObj)
        {
diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index c247fdbf..cda4214 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -447,7 +447,7 @@
void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFormatItem& rFormats )
{
    vcl::Window* pWin = GetViewData()->GetActiveWin();
    bool bDraw = ScDrawTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) != nullptr;
    bool bDraw = ScDrawTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin)) != nullptr;

    TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );

@@ -478,10 +478,11 @@

//  insert, insert contents

static bool lcl_IsCellPastePossible( const TransferableDataHelper& rData, ScTabViewShell* pViewShell )
static bool lcl_IsCellPastePossible( const TransferableDataHelper& rData )
{
    bool bPossible = false;
    if ( ScTransferObj::GetOwnClipboard(pViewShell->GetClipData()) || ScDrawTransferObj::GetOwnClipboard(pViewShell->GetClipData()) )
    css::uno::Reference< css::datatransfer::XTransferable2 > xTransferable(rData.GetXTransferable(), css::uno::UNO_QUERY);
    if ( ScTransferObj::GetOwnClipboard(xTransferable) || ScDrawTransferObj::GetOwnClipboard(xTransferable) )
        bPossible = true;
    else
    {
@@ -520,19 +521,7 @@

IMPL_LINK( ScCellShell, ClipboardChanged, TransferableDataHelper*, pDataHelper, void )
{
    ScTabViewShell* pViewShell = GetViewData()->GetViewShell();
    css::uno::Reference<css::datatransfer::XTransferable2> xOldTransfer(pViewShell->GetClipData());
    css::uno::Reference<css::datatransfer::XTransferable2> xNewTransfer(pDataHelper->GetXTransferable(), css::uno::UNO_QUERY);

    if ( xNewTransfer.get() != xOldTransfer.get() )
    {
        if ( ScTransferObj::GetOwnClipboard(xNewTransfer) || ScDrawTransferObj::GetOwnClipboard(xNewTransfer) )
            pViewShell->SetClipData(xNewTransfer);
        else
            pViewShell->SetClipData(css::uno::Reference<css::datatransfer::XTransferable2>());
    }

    bPastePossible = lcl_IsCellPastePossible( *pDataHelper, pViewShell );
    bPastePossible = lcl_IsCellPastePossible( *pDataHelper );

    SfxBindings& rBindings = GetViewData()->GetBindings();
    rBindings.Invalidate( SID_PASTE );
@@ -567,7 +556,7 @@
    if (!pWin)
        return false;

    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(rViewData.GetViewShell()->GetClipData());
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin));
    if (!pOwnClip)
        // If it's not a Calc document, we won't be picky.
        return true;
@@ -606,7 +595,7 @@

        // get initial state
        TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
        bPastePossible = lcl_IsCellPastePossible( aDataHelper, GetViewData()->GetViewShell() );
        bPastePossible = lcl_IsCellPastePossible( aDataHelper );
    }

    bool bDisable = !bPastePossible;
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 2df5212..35bb8dc 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -1292,8 +1292,9 @@

                if ( nFormat != SotClipboardFormatId::NONE )
                {
                    bool bCells = ( ScTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) != nullptr );
                    bool bDraw = ( ScDrawTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) != nullptr );
                    css::uno::Reference<css::datatransfer::XTransferable2> xTransferable(ScTabViewShell::GetClipData(GetViewData()->GetActiveWin()));
                    bool bCells = ( ScTransferObj::GetOwnClipboard(xTransferable) != nullptr );
                    bool bDraw = ( ScDrawTransferObj::GetOwnClipboard(xTransferable) != nullptr );
                    bool bOle = ( nFormat == SotClipboardFormatId::EMBED_SOURCE );

                    if ( bCells && bOle )
@@ -1320,7 +1321,7 @@
                ScDocument* pDoc = GetViewData()->GetDocument();
                bool bOtherDoc = !pDoc->IsClipboardSource();
                // keep a reference in case the clipboard is changed during dialog or PasteFromClip
                const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData());
                const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(GetViewData()->GetActiveWin()));
                if ( pOwnClip )
                {
                    bool bSkipEmpty = false;
@@ -1473,7 +1474,7 @@
        case SID_PASTE_ONLY_TEXT:
        case SID_PASTE_ONLY_FORMULA:
        {
            if ( ScTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) )  // own cell data
            if ( ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(GetViewData()->GetActiveWin())) )  // own cell data
            {
                rReq.SetSlot( FID_INS_CELL_CONTENTS );
                OUString aFlags;
@@ -1497,6 +1498,7 @@
            // this makes FID_INS_CELL_CONTENTS superfluous
            {
                vcl::Window* pWin = GetViewData()->GetActiveWin();
                css::uno::Reference<css::datatransfer::XTransferable2> xTransferable(ScTabViewShell::GetClipData(pWin));

                //  Clipboard-ID given as parameter? Basic "PasteSpecial(Format)"
                const SfxPoolItem* pItem=nullptr;
@@ -1508,7 +1510,7 @@
                    bool bRet=true;
                    {
                        WaitObject aWait( GetViewData()->GetDialogParent() );
                        bool bDraw = ( ScDrawTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) != nullptr );
                        bool bDraw = ( ScDrawTransferObj::GetOwnClipboard(xTransferable) != nullptr );
                        if ( bDraw && nFormat == SotClipboardFormatId::EMBED_SOURCE )
                            pTabViewShell->PasteDraw();
                        else
@@ -1527,7 +1529,7 @@

                if ( !pItem )
                {
                    if ( ScTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) )  // own cell data
                    if ( ScTransferObj::GetOwnClipboard(xTransferable) )  // own cell data
                    {
                        rReq.SetSlot( FID_INS_CELL_CONTENTS );
                        ExecuteSlot( rReq, GetInterface() );
@@ -1535,7 +1537,7 @@
                    }
                    else                                    // draw objects or external data
                    {
                        bool bDraw = ( ScDrawTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) != nullptr );
                        bool bDraw = ( ScDrawTransferObj::GetOwnClipboard(xTransferable) != nullptr );

                        SvxClipboardFormatItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
                        GetPossibleClipboardFormats( aFormats );
diff --git a/sc/source/ui/view/cliputil.cxx b/sc/source/ui/view/cliputil.cxx
index 254352d..21d642c 100644
--- a/sc/source/ui/view/cliputil.cxx
+++ b/sc/source/ui/view/cliputil.cxx
@@ -46,7 +46,7 @@

void ScClipUtil::PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTabViewShell, bool bShowDialog )
{
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(pTabViewShell->GetClipData());
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pViewData->GetActiveWin()));
    ScDocument* pThisDoc = pViewData->GetDocument();
    ScDPObject* pDPObj = pThisDoc->GetDPAtCursor( pViewData->GetCurX(),
                         pViewData->GetCurY(), pViewData->GetTabNo() );
diff --git a/sc/source/ui/view/drawvie4.cxx b/sc/source/ui/view/drawvie4.cxx
index aaeb6f7..5a123ae 100644
--- a/sc/source/ui/view/drawvie4.cxx
+++ b/sc/source/ui/view/drawvie4.cxx
@@ -380,7 +380,6 @@
        pTransferObj->SetDrawPersist( ScGlobal::xDrawClipDocShellRef.get() );    // keep persist for ole objects alive
    }

    pViewData->GetViewShell()->SetClipData(xTransferObj); // internal clipboard
    pTransferObj->CopyToClipboard( pViewData->GetActiveWin() );     // system clipboard
}

diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index a1598a2..1e45e78 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -5751,7 +5751,7 @@
    rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
    if (!xOverlayManager.is())
        return;
    const ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard(pViewData->GetViewShell()->GetClipData());
    const ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pViewData->GetActiveWin()));
    if (!pTransObj)
        return;
    ScDocument* pClipDoc = pTransObj->GetDocument();
diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx
index e877e28..c3d4516 100644
--- a/sc/source/ui/view/tabvwshc.cxx
+++ b/sc/source/ui/view/tabvwshc.cxx
@@ -542,6 +542,22 @@
        pWin->updateLibreOfficeKitCellCursor(pOtherShell);
}

css::uno::Reference<css::datatransfer::XTransferable2> ScTabViewShell::GetClipData(vcl::Window* pWin)
{
    SfxViewFrame* pViewFrame = nullptr;
    css::uno::Reference<css::datatransfer::XTransferable2> xTransferable;
    css::uno::Reference<css::datatransfer::clipboard::XClipboard> xClipboard;

    if (pWin)
        xClipboard = pWin->GetClipboard();
    else if ((pViewFrame = SfxViewFrame::GetFirst(nullptr, false)))
        xClipboard = pViewFrame->GetWindow().GetClipboard();

    xTransferable.set(xClipboard.is() ? xClipboard->getContents() : nullptr, css::uno::UNO_QUERY);

    return xTransferable;
}

void ScTabViewShell::notifyAllViewsHeaderInvalidation(HeaderType eHeaderType, SCTAB nCurrentTabIndex)
{
    if (comphelper::LibreOfficeKit::isActive())
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index cb71f16..bc41b1e 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -279,7 +279,6 @@
                    pTransferObj->SetDrawPersist( aPersistRef );// keep persist for ole objects alive

                }
                GetViewData().GetViewShell()->SetClipData(xTransferObj);
                pTransferObj->CopyToClipboard( GetActiveWin() );
            }

@@ -386,7 +385,6 @@
                    SfxObjectShellRef aPersistRef( ScGlobal::xDrawClipDocShellRef.get() );
                    pTransferObj->SetDrawPersist( aPersistRef );    // keep persist for ole objects alive
                }
                GetViewData().GetViewShell()->SetClipData(xTransferObj);
                pTransferObj->CopyToClipboard( GetActiveWin() );    // system clipboard
            }

@@ -448,7 +446,7 @@
    vcl::Window* pWin = GetActiveWin();
    Point aPos = pWin->PixelToLogic( rViewData.GetScrPos( nPosX, nPosY,
                                     rViewData.GetActivePart() ) );
    const ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard(GetViewData().GetViewShell()->GetClipData());
    const ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(rViewData.GetActiveWin()));
    if (pDrawClip)
    {
        OUString aSrcShellID = pDrawClip->GetShellID();
@@ -462,9 +460,10 @@
    UpdateInputLine();

    vcl::Window* pWin = GetActiveWin();
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(GetViewData().GetViewShell()->GetClipData());
    css::uno::Reference<css::datatransfer::XTransferable2> xTransferable2(ScTabViewShell::GetClipData(pWin));
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(xTransferable2);
    // keep a reference in case the clipboard is changed during PasteFromClip
    const ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard(GetViewData().GetViewShell()->GetClipData());
    const ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard(xTransferable2);
    if (pOwnClip)
    {
        PasteFromClip( InsertDeleteFlags::ALL, pOwnClip->GetDocument(),
@@ -707,7 +706,7 @@
    bool bRet = true;
    vcl::Window* pWin = GetActiveWin();
    // keep a reference in case the clipboard is changed during PasteFromClip
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(GetViewData().GetViewShell()->GetClipData());
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin));
    if ( nFormatId == SotClipboardFormatId::NONE && pOwnClip )
    {
        PasteFromClip( InsertDeleteFlags::ALL, pOwnClip->GetDocument(),
diff --git a/sc/source/ui/view/viewfun7.cxx b/sc/source/ui/view/viewfun7.cxx
index a944754..4258b33 100644
--- a/sc/source/ui/view/viewfun7.cxx
+++ b/sc/source/ui/view/viewfun7.cxx
@@ -250,7 +250,7 @@
        ScDocument* pDocument = GetViewData().GetDocument();
        ScDocShell* pDocShell = GetViewData().GetDocShell();
        ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : nullptr );
        const ScDrawTransferObj* pTransferObj = ScDrawTransferObj::GetOwnClipboard(GetViewData().GetViewShell()->GetClipData());
        const ScDrawTransferObj* pTransferObj = ScDrawTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(GetViewData().GetActiveWin()));
        if ( pDocument && pPage && pModelObj && ( pTransferObj || pDrawTrans ) )
        {
            const ScRangeListVector& rProtectedChartRangesVector(